/*******************************************************************************
 * Copyright (c) 2011-11-10 @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> - initial API and implementation
 ******************************************************************************/
package com.redhat.auth.ejb.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.redhat.auth.domain.Account;
import com.redhat.auth.domain.BizSystem;
import com.redhat.auth.domain.BizSystemBinding;
import com.redhat.auth.domain.FunctionEntity;
import com.redhat.auth.domain.FunctionEntityType;
import com.redhat.auth.domain.Role;
import com.redhat.auth.domain.SecurityStrategy;
import com.redhat.auth.ejb.vo.AccountVO;
import com.redhat.auth.ejb.vo.BizSystemBindingVO;
import com.redhat.auth.ejb.vo.BizSystemVO;
import com.redhat.auth.ejb.vo.FunctionEntityTypeVO;
import com.redhat.auth.ejb.vo.FunctionEntityVO;
import com.redhat.auth.ejb.vo.RoleVO;
import com.redhat.auth.ejb.vo.SecurityStrategyVO;

/**
 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
 * @since 2011-11-10
 */
public final class Convertor {
	private Convertor() {
	}

	public static Account vo2po(AccountVO vo, Account account) {
		if (vo == null) {
			return account;
		}
		account.setId(vo.getId());
		account.setDescription(vo.getDescription());
		account.setEmail(vo.getEmail());
		if (vo.getLocked() != null && vo.getLocked()) {
			account.lock();
		} else {
			account.unlock();
		}
		account.setPassword(vo.getPassword());
		account.setPasswordLastUpdateDate(vo.getPasswordLastUpdateDate());
		account.setRealName(vo.getRealName());
		account.setRegistryDate(vo.getRegistryDate());
		account.setUsername(vo.getUsername());
		return account;
	}

	public static BizSystemBinding vo2po(BizSystemBindingVO vo,
			BizSystemBinding binding) {
		if (vo == null) {
			return binding;
		}
		if (vo.getStatus() == BizSystemBinding.Status.ENABLED.ordinal()) {
			binding.setStatus(BizSystemBinding.Status.ENABLED);
		} else {
			binding.setStatus(BizSystemBinding.Status.DISABLED);
		}
		return binding;
	}

	public static BizSystem vo2po(BizSystemVO vo, BizSystem system) {
		if (vo == null) {
			return system;
		}
		system.setId(vo.getId());
		system.setDescription(vo.getDescription());
		system.setName(vo.getName());
		system.setRegistryDate(vo.getRegistryDate());
		system.setSerialNumber(vo.getSerialNumber());
		if (vo.getStatus() == BizSystem.Status.ENABLED.ordinal()) {
			system.setStatus(BizSystem.Status.ENABLED);
		} else {
			system.setStatus(BizSystem.Status.DISABLED);
		}
		system.setUrl(vo.getUrl());
		return system;
	}

	public static FunctionEntityType vo2po(FunctionEntityTypeVO vo) {
		if (vo == null) {
			return null;
		}
		return new FunctionEntityType(vo.getId(), vo.getName(), vo2po(vo
				.getParent()));
	}

	public static FunctionEntity vo2po(FunctionEntityVO vo,
			FunctionEntity entity) {
		if (vo == null) {
			return entity;
		}
		entity.setId(vo.getId());
		entity.setName(vo.getName());
		entity.setAlias(vo.getAlias());
		entity.setDescription(vo.getDescription());
		if (FunctionEntity.Status.ENABLED.ordinal() == vo.getStatus()) {
			entity.setStatus(FunctionEntity.Status.ENABLED);
		} else {
			entity.setStatus(FunctionEntity.Status.DISABLED);
		}
		entity.setFunctionEntityType(vo2po(vo.getFunctionEntityType()));
		if (vo.getParent() != null) {
			vo.getParent().setParent(null);
			entity.setParent(vo2po(vo.getParent(), new FunctionEntity()));
		}
		return entity;
	}

	public static Role vo2po(RoleVO vo, Role role) {
		if (vo == null) {
			return role;
		}
		role.setId(vo.getId());
		role.setName(vo.getName());
		role.setDescription(vo.getDescription());
		if (Role.Status.ENABLED.ordinal() == vo.getStatus()) {
			role.setStatus(Role.Status.ENABLED);
		} else {
			role.setStatus(Role.Status.DISABLED);
		}
		return role;
	}

	public static SecurityStrategy vo2po(SecurityStrategyVO vo,
			SecurityStrategy strategy) {
		if (vo == null) {
			return strategy;
		}
		strategy.setId(vo.getId());
		strategy.setAutoUnlockHours(vo.getAutoUnlockHours());
		strategy.setLoginTimes(vo.getLoginTimes());
		strategy.setLoginTimesMinuteLimit(vo.getLoginTimesMinuteLimit());
		if (vo.getNeedCaptcha() != null && vo.getNeedCaptcha()) {
			strategy.needCaptcha();
		} else {
			strategy.unNeedCaptcha();
		}
		int o = vo.getPasswordComplexity();
		if (SecurityStrategy.PasswordComplexity.LETTER.ordinal() == o) {
			strategy
					.setPasswordComplexity(SecurityStrategy.PasswordComplexity.LETTER);
		} else if (SecurityStrategy.PasswordComplexity.NUMERIC.ordinal() == o) {
			strategy
					.setPasswordComplexity(SecurityStrategy.PasswordComplexity.NUMERIC);
		} else if (SecurityStrategy.PasswordComplexity.NUMERIC_AND_LETTER
				.ordinal() == o) {
			strategy
					.setPasswordComplexity(SecurityStrategy.PasswordComplexity.NUMERIC_AND_LETTER);
		} else {
			strategy
					.setPasswordComplexity(SecurityStrategy.PasswordComplexity.UNRESTRICTED);
		}
		strategy.setPasswordExpiredDays(vo.getPasswordExpiredDays());
		strategy.setPasswordMinLength(vo.getPasswordMinLength());
		return strategy;
	}

	//
	public static AccountVO po2vo(Account account, Map map) {
		if (account == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, account)) {
			return (AccountVO) map.get(account);
		}
		AccountVO vo = new AccountVO();
		{
			vo.setId(account.getId());
			vo.setDescription(account.getDescription());
			vo.setEmail(account.getEmail());
			if (account.isLock()) {
				vo.setLocked(true);
			} else {
				vo.setLocked(false);
			}
			//vo.setPassword(account.getPassword());
			vo.setPasswordLastUpdateDate(account.getPasswordLastUpdateDate());
			vo.setRealName(account.getRealName());
			vo.setRegistryDate(account.getRegistryDate());
			vo.setUsername(account.getUsername());
			vo.setRoles((Set) po2vo(account.getRoles(), new HashSet(), map));
			vo.setBizSystemBindings((Set) po2vo(account.getBizSystemBindings(),
					new HashSet(), map));
		}
		{
			setReference(map, account, vo);
		}
		return vo;
	}

	public static BizSystemBindingVO po2vo(BizSystemBinding binding, Map map) {
		if (binding == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, binding)) {
			return (BizSystemBindingVO) map.get(binding);
		}
		BizSystemBindingVO vo = new BizSystemBindingVO();
		{
			vo.setBizSystem(po2vo(binding.getBizSystem(), map));
			vo.setStatus(ordinal(binding.getStatus()));
		}
		{
			setReference(map, binding, vo);
		}
		return vo;
	}

	public static BizSystemVO po2vo(BizSystem system, Map map) {
		if (system == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, system)) {
			return (BizSystemVO) map.get(system);
		}
		BizSystemVO vo = new BizSystemVO();
		{
			vo.setDescription(system.getDescription());
			vo.setId(system.getId());
			vo.setName(system.getName());
			vo.setRegistryDate(system.getRegistryDate());
			vo.setSerialNumber(system.getSerialNumber());
			vo.setStatus(ordinal(system.getStatus()));
			vo.setUrl(system.getUrl());
		}
		{
			setReference(map, system, vo);
		}
		return vo;
	}

	public static FunctionEntityTypeVO po2vo(FunctionEntityType type, Map map) {
		if (type == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, type)) {
			return (FunctionEntityTypeVO) map.get(type);
		}
		FunctionEntityTypeVO vo = new FunctionEntityTypeVO();
		{
			vo.setId(type.getId());
			vo.setName(type.getName());
		}
		{
			setReference(map, type, vo);
		}
		return vo;
	}

	public static FunctionEntityVO po2vo(FunctionEntity entity, Map map) {
		if (entity == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, entity)) {
			return (FunctionEntityVO) map.get(entity);
		}
		FunctionEntityVO vo = new FunctionEntityVO();
		{
			vo.setId(entity.getId());
			vo.setName(entity.getName());
			vo.setAlias(entity.getAlias());
			vo.setDescription(entity.getDescription());
			vo
					.setFunctionEntityType(po2vo(
							entity.getFunctionEntityType(), map));
			vo.setParent(po2vo(entity.getParent(), map));
			vo.setStatus(ordinal(entity.getStatus()));
		}
		{
			setReference(map, entity, vo);
		}
		return vo;
	}

	public static RoleVO po2vo(Role role, Map map) {
		if (role == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, role)) {
			return (RoleVO) map.get(role);
		}
		RoleVO vo = new RoleVO();
		{
			vo.setId(role.getId());
			vo.setName(role.getName());
			vo.setDescription(role.getDescription());
			vo.setFunctionEntities((Set) po2vo(role.getFunctionEntities(),
					new HashSet(), map));
			vo.setStatus(ordinal(role.getStatus()));
		}
		{
			setReference(map, role, vo);
		}
		return vo;
	}

	public static SecurityStrategyVO po2vo(SecurityStrategy strategy, Map map) {
		if (strategy == null) {
			return null;
		}
		{
			map = map == null ? new HashMap() : map;
		}
		if (contains(map, strategy)) {
			return (SecurityStrategyVO) map.get(strategy);
		}
		SecurityStrategyVO vo = new SecurityStrategyVO();
		{
			vo.setId(strategy.getId());
			vo.setAutoUnlockHours(strategy.getAutoUnlockHours());
			vo.setLoginTimes(strategy.getLoginTimes());
			vo.setLoginTimesMinuteLimit(strategy.getLoginTimesMinuteLimit());
			if (strategy.isNeedCaptcha()) {
				vo.setNeedCaptcha(true);
			} else {
				vo.setNeedCaptcha(false);
			}
			vo.setPasswordComplexity(ordinal(strategy.getPasswordComplexity()));
			vo.setPasswordExpiredDays(strategy.getPasswordExpiredDays());
			vo.setPasswordMinLength(strategy.getPasswordMinLength());
		}
		{
			setReference(map, strategy, vo);
		}
		return vo;
	}

	public static Collection po2vo(Collection sets, Collection result, Map map) {
		if (sets == null || sets.isEmpty() || result == null) {
			return result;
		}
		Collection c = result;
		for (Iterator it = sets.iterator(); it.hasNext();) {
			Object next = it.next();
			if (next instanceof Account) {
				c.add(po2vo((Account) next, map));
			} else if (next instanceof BizSystemBinding) {
				c.add(po2vo((BizSystemBinding) next, map));
			} else if (next instanceof BizSystem) {
				c.add(po2vo((BizSystem) next, map));
			} else if (next instanceof FunctionEntityType) {
				c.add(po2vo((FunctionEntityType) next, map));
			} else if (next instanceof FunctionEntity) {
				c.add(po2vo((FunctionEntity) next, map));
			} else if (next instanceof Role) {
				c.add(po2vo((Role) next, map));
			} else if (next instanceof SecurityStrategy) {
				c.add(po2vo((SecurityStrategy) next, map));
			} else {
				break;
			}
		}
		return c;
	}

	private static Map setReference(Map map, Object key, Object value) {
		map = map == null ? new HashMap() : map;
		map.put(key, value);
		return map;
	}

	private static boolean contains(Map map, Object key) {
		return map == null ? false : map.containsKey(key);
	}

	private static int ordinal(Enum e) {
		return e == null ? 0 : e.ordinal();
	}
}
